﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Diagnostics;
using System.ComponentModel;
using System.Windows.Data;
using System.Windows.Media.Imaging;
using System.Collections.ObjectModel;

namespace BattleforgeAssault
{
    public partial class CardView : UserControl
    {
        public Card Card { get { return DataContext as Card; } }

        private bool _isFlipped = false;

        public CardView()
        {
            InitializeComponent();
        }

        #region Event Handlers

        private void OnMouseEnter(object sender, MouseEventArgs e)
        {
            // TODO: this is where we can replace the current tooltip effect with something better
        }

        private void OnMouseDown(object sender, MouseButtonEventArgs e)
        {
            FrameworkElement element = sender as FrameworkElement;
            Card card = element.DataContext as Card;
            Game game = card.Game;
            Controller controller = game.Controller;

            if (game.State == Types.States.Targeting)
            {
                if (game.Controller.CurrentTargets.Contains(card))
                {
                    game.Controller.CurrentTargets.Remove(card);
                    Select(false);
                }
                else
                {
                    game.Controller.CurrentTargets.Add(card);
                    Select(true);
                }
            }
        }

        private void OnRightMouseDown(object sender, MouseButtonEventArgs e)
        {
            ToggleMenu();

            e.Handled = true;
        }

        private void ToggleMenu()
        {
            // check type for which buttons to hide
            if (!(Card is Unit)) { addDamageButton.Visibility = Visibility.Collapsed; removeDamageButton.Visibility = Visibility.Collapsed; }

            if (menu.Opacity == 1)
            {
                Util.PlayDoubleAnimation(105, 0, 0.5, menu, WidthProperty);
                Util.PlayDoubleAnimation(150, 0, 0.5, menu, HeightProperty);
                Util.PlayDoubleAnimation(1, 0, .5, menu, OpacityProperty);
                Canvas.SetZIndex(this, 0);
            }
            else
            {
                Util.PlayDoubleAnimation(0, 105, 0.5, menu, WidthProperty);
                Util.PlayDoubleAnimation(0, 150, 0.5, menu, HeightProperty);
                Util.PlayDoubleAnimation(0, 1, .5, menu, OpacityProperty);
                Canvas.SetZIndex(this, 1);
            }
        }

        #endregion Event Handlers

        /// <summary>
        /// Selects this card.
        /// </summary>
        /// <param name="value">True to select, false to unselect.</param>
        public void Select(bool value)
        {
            if (value) { TranslateVertical(0, -32, 0.5); }
            else { TranslateVertical(-32, 0, 0.5); }
        }

        /// <summary>
        /// Dims this card (to show an invalid target).
        /// </summary>
        /// <param name="value">True to dim, false to undim.</param>
        public void Dim(bool value)
        {
            if (value) { Util.PlayDoubleAnimation(0, .4, .5, dimmer, OpacityProperty); }
            else { Util.PlayDoubleAnimation(.4, 0, .5, dimmer, OpacityProperty); }
        }

        #region Animation Methods

        public void Rotate(double from, double to, double duration)
        {
            Util.PlayDoubleAnimation(from, to, duration, rotation, RotateTransform.AngleProperty);
        }

        public void TranslateVertical(double from, double to, double duration)
        {
            Util.PlayDoubleAnimation(from, to, duration, translation, TranslateTransform.YProperty);
        }

        public void TranslateHorizontal(double from, double to, double duration)
        {
            Util.PlayDoubleAnimation(from, to, duration, translation, TranslateTransform.XProperty);
        }

        public void Flip(double duration)
        {
            var shrink = Util.PlayDoubleAnimation(1, .02, duration / 2, scale, ScaleTransform.ScaleXProperty);
            shrink.Completed += (s, e) =>
                {
                    var binding = new Binding();
                    if (_isFlipped) { binding.Source = Card.Front; }
                    else { binding.Source = Card.Back; }

                    BindingOperations.SetBinding(cardImage, Image.SourceProperty, binding);

                    Util.PlayDoubleAnimation(.02, 1, duration / 2, scale, ScaleTransform.ScaleXProperty);
                    _isFlipped = !_isFlipped;
                };
        }

        #endregion Animation Methods

        private void OnRotateClick(object sender, RoutedEventArgs e)
        {
            Card.IsCorrupt = !Card.IsCorrupt;
            ToggleMenu();
        }

        private void OnAddDamageClick(object sender, RoutedEventArgs e)
        {
            if (Card is Unit) { ((Unit)Card).DamageTaken++; }
        }

        private void OnFlipClick(object sender, RoutedEventArgs e)
        {
            Card.IsDeveloped = !Card.IsDeveloped;
            ToggleMenu();
        }

        private void OnAddTokenClick(object sender, RoutedEventArgs e)
        {
            Card.Tokens++;
        }

        private void OnMoveClick(object sender, RoutedEventArgs e)
        {
            Game game = Card.Game;

            var targets = game.ActivePlayer.SelectTargets("Select location", 1, 1, (t) =>
                {
                    return (t is Location);
                });

            if (targets != null && targets[0] is Location)
            {
                Location location = targets[0] as Location;
                game.ActivePlayer.MoveCardTo(Card, location);
                ToggleMenu();
            }
        }

        private void OnRemoveTokenClick(object sender, RoutedEventArgs e)
        {
            Card.Tokens--;
        }

        private void OnRemoveDamageClick(object sender, RoutedEventArgs e)
        {
            if (Card is Unit) { ((Unit)Card).DamageTaken--; }
        }
    } // CardView class

    public class IntToListConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            int numItems = (int)value;
            List<object> list = new List<object>();

            for (int i = 0; i < numItems; i++)
            {
                list.Add(new object());
            }

            return list;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            List<object> list = value as List<object>;

            return list.Count;
        }
    } // IntToListConverter class
} // Namespace
